﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Smartec.Accounts.Camel.AMS.Model.Entities;
using Smartec.Framework.Common.CachingManager;
using Smartec.Framework.Common;
using System.Reflection;
using Smartec.Accounts.Camel.AMS.Model.Repository;
using System.Data.Objects;
using System.ComponentModel.DataAnnotations;

namespace Smartec.Accounts.Camel.AMS.Model
{
    /// <summary>
    /// ObjectContextHelper classes. 
    /// </summary>
    internal static class AMSObjectContextHelper
    {
        private static object locker = new object();
        #region AMSEntitiesConnectionString
        private static string amsEntitiesConnectionString = null;
        public static string AMSEntitiesConnectionString
        {
            get
            {
                if (amsEntitiesConnectionString == null)
                    lock (locker)
                        return ConfigurationBase.ApplicationConfiguration.GetValue("configuration/dataaccess/AMSEntities_connection_string");
                return amsEntitiesConnectionString;
            }
            set
            {
                amsEntitiesConnectionString = value;
            }
        }
        #endregion // AMSEntitiesConnectionString

        /// <summary>
        /// Gets an object context
        /// </summary>
        public static AMSObjectContext CurrentObjectContext
        {
            get
            {
                return ObjectCachingManager.GetObjectContext<AMSObjectContext>("ams", AMSEntitiesConnectionString);
            }
        }


        //#region GetTableByName
        //public static IEnumerable<T> GetTableByName<T>(string tableName) where T : class
        //{
        //    return (IEnumerable<T>)CurrentObjectContext.GetType().GetProperty(tableName).GetValue(CurrentObjectContext, null);
        //}
        //#endregion // GetTableByName

        #region GetListItemsByTableName
        public static List<KeyValuePair<string, string>> GetListItemsByTableName(string tableName)
        {
            List<KeyValuePair<string, string>> listItems = new List<KeyValuePair<string, string>>();

            IEnumerable<object> table = (IEnumerable<object>)CurrentObjectContext.GetType().GetProperty(tableName).GetValue(CurrentObjectContext, null);
            try
            {
                table = table.OrderBy(o => o.GetType().GetProperty("Displayorder"));
            }
            catch (Exception)
            {
                    
                //throw;
            }
           
            foreach (var entity in table)
            {
                object key = ((PropertyInfo)entity.GetType().GetProperty("ID")).GetValue(entity, null);
                object value = ((PropertyInfo)entity.GetType().GetProperty("DisplayName")).GetValue(entity, null);
                listItems.Add(new KeyValuePair<string, string>(key.ToString(), value.ToString()));
            }
            return listItems/*.OrderBy(o => o.Value).ToList()*/;
        }
        #endregion // GetListItemsByTableName

        #region GetListItemsByMethodName
        public static List<KeyValuePair<string, string>> GetListItemsByMethodName(string methodName, string parameter)
        {
            List<KeyValuePair<string, string>> listItems = new List<KeyValuePair<string, string>>();

            Type t = Type.GetType("Smartec.Accounts.Camel.AMS.Model.Managers.ForiegnFieldManager");
            MethodInfo method = t.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public);

            listItems = (List<KeyValuePair<string, string>>)method.Invoke(t, new string[] { parameter });

            return listItems;
        }
        #endregion // GetListItemsByMethodName

        #region GetListItems
        public static List<KeyValuePair<string, string>> GetListItems(string entityName, string parameterName, string parameterValue)
        {
            List<KeyValuePair<string, string>> listItems = new List<KeyValuePair<string, string>>();

            string queryString = "";
            IEnumerable<object> objectQuery;

            if (!string.IsNullOrEmpty(parameterName) && !string.IsNullOrEmpty(parameterValue))
            {
                int whereParameterValue = Int32.Parse(parameterValue);//o.ID AS ID,o.Name_EN AS DisplayName
                queryString = string.Format(@"SELECT VALUE o FROM AMSObjectContext.{0} AS o WHERE o.{1} = @parameterValue", entityName, parameterName);
                objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, new ObjectParameter("parameterValue", whereParameterValue));
            }
            else
            {
                queryString = string.Format(@"SELECT VALUE o FROM AMSObjectContext.{0} AS o", entityName);
                objectQuery = CurrentObjectContext.CreateQuery<object>(queryString);
            }

            try
            {
                objectQuery = objectQuery.OrderBy(o => o.GetType().GetProperty("Displayorder"));
            }
            catch (Exception)
            {

                //throw;
            }

            foreach (var entity in objectQuery)
            {
                object key = ((PropertyInfo)entity.GetType().GetProperty("ID")).GetValue(entity, null);
                object value = ((PropertyInfo)entity.GetType().GetProperty("DisplayName")).GetValue(entity, null);
                listItems.Add(new KeyValuePair<string, string>(key.ToString(), value.ToString()));
            }
            return listItems/*.OrderBy(o => o.Value).ToList()*/;

            //string queryString = "";
            //ObjectQuery<DbDataRecord> objectQuery;

            //if (!string.IsNullOrEmpty(parameterName) && !string.IsNullOrEmpty(parameterValue))
            //{
            //    int whereParameterValue = Int32.Parse(parameterValue);//o.ID AS ID,o.Name_EN AS DisplayName
            //    queryString = string.Format(@"SELECT o.ID, o.DisplayName, o.Name_EN FROM AMSObjectContext.{0} AS o WHERE o.{1} = @parameterValue", entityName, parameterName);
            //    objectQuery = CurrentObjectContext.CreateQuery<DbDataRecord>(queryString, new ObjectParameter("parameterValue", whereParameterValue));
            //}
            //else
            //{
            //    queryString = string.Format(@"SELECT o.ID, o.DisplayName, o.Name_EN FROM AMSObjectContext.{0} AS o", entityName);
            //    objectQuery = CurrentObjectContext.CreateQuery<DbDataRecord>(queryString);
            //}

            //ObjectResult<DbDataRecord> results = objectQuery.Execute(MergeOption.NoTracking);
            //foreach (DbDataRecord record in results)
            //{
            //    listItems.Add(new KeyValuePair<string, string>(Convert.ToString(record[0]), Convert.ToString(record[1])));
            //}
        }
        #endregion // GetListItems

        #region IsExist
        public static bool IsExist(string entityName, string parameterName, string parameterValue, int? curruntID)
        {
            string queryString = "";
            IEnumerable<object> objectQuery = null;

            if (!string.IsNullOrEmpty(parameterName) && !string.IsNullOrEmpty(parameterValue))
            {
                if (curruntID.HasValue)
                {
                    queryString = string.Format(@"SELECT VALUE o.ID FROM AMSObjectContext.{0} AS o WHERE o.ID != @id And ToLower(Trim(o.{1})) = @parameterValue", entityName, parameterName);
                    ObjectParameter[] objectParameters = { new ObjectParameter("parameterValue", parameterValue.Trim().ToLower()), new ObjectParameter("id", curruntID.Value) };
                    objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, objectParameters);
                }
                else
                {
                    queryString = string.Format(@"SELECT VALUE o.ID FROM AMSObjectContext.{0} AS o WHERE ToLower(Trim(o.{1})) = @parameterValue", entityName, parameterName);
                    objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, new ObjectParameter("parameterValue", parameterValue.Trim().ToLower()));
                }
            }

            return objectQuery != null && objectQuery.Count() > 0;

        }

        public static bool IsExistNoneStringProperty(string entityName, string parameterName, string parameterValue, int? curruntID)
        {
            string queryString = "";
            IEnumerable<object> objectQuery = null;

            if (!string.IsNullOrEmpty(parameterName) && !string.IsNullOrEmpty(parameterValue))
            {
                if (curruntID.HasValue)
                {
                    queryString = string.Format(@"SELECT VALUE o.ID FROM AMSObjectContext.{0} AS o WHERE o.ID != @id And ToLower(Trim(SqlServer.STR(o.{1}))) = @parameterValue", entityName, parameterName);
                    ObjectParameter[] objectParameters = { new ObjectParameter("parameterValue", parameterValue.Trim().ToLower()), new ObjectParameter("id", curruntID.Value) };
                    objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, objectParameters);
                }
                else
                {
                    queryString = string.Format(@"SELECT VALUE o.ID FROM AMSObjectContext.{0} AS o WHERE ToLower(Trim(SqlServer.STR(o.{1}))) = @parameterValue", entityName, parameterName);
                    objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, new ObjectParameter("parameterValue", parameterValue.Trim().ToLower()));
                }
            }

            return objectQuery != null && objectQuery.Count() > 0;

        }
        #endregion // IsExist

        #region GetFieldValue
        public static int? GetFieldValue(string entityName, string propertyName, int id)
        {
            string queryString = string.Format(@"SELECT VALUE o.{1} FROM AMSObjectContext.{0} AS o WHERE o.ID = @id", entityName, propertyName);

            int? fieldValue = (int?)CurrentObjectContext.CreateQuery<object>(queryString, new ObjectParameter("id", id)).FirstOrDefault();

            return fieldValue;
        }
        #endregion //GetFieldValue

        #region GetItemNameByTableNameAndID
        public static string GetItemNameByTableNameAndID(string tableName, int ID)
        {
            string displayName = "";

            string queryString = string.Format(@"SELECT VALUE o FROM AMSObjectContext.{0} AS o WHERE o.ID = @id", tableName);

            object objectQuery = CurrentObjectContext.CreateQuery<object>(queryString, new ObjectParameter("id", ID)).FirstOrDefault();

            //IEnumerable<object>  table = (IEnumerable<object>)CurrentObjectContext.GetType().GetProperty(tableName).GetValue(CurrentObjectContext, null);

            //foreach (var entity in table)
            //{
            //if (ID == Int32.Parse(((PropertyInfo)entity.GetType().GetProperty("ID")).GetValue(entity, null).ToString()))
            //{
            if (objectQuery != null)
            {
                PropertyInfo pi = (PropertyInfo)objectQuery.GetType().GetProperty("DisplayName");
                if (pi != null)
                {
                    displayName = Convert.ToString(pi.GetValue(objectQuery, null));
                }
                else
                {
                    displayName = ID.ToString();
                }
            }
            else
            {
                displayName = ID.ToString();
            }
            //break;
            //}
            //}
            return displayName;
        }
        #endregion // GetItemNameByTableNameAndID

        #region GetPropertyMetaData
        public static PropertyInfo GetPropertyMetaData(PropertyInfo property)
        {
            var atts = property.DeclaringType.GetCustomAttributes(typeof(MetadataTypeAttribute), true);
            if (atts.Length == 0)
                return null;

            var metaAttr = atts[0] as MetadataTypeAttribute;
            var metaProperty =
                metaAttr.MetadataClassType.GetProperty(property.Name);
            return metaProperty;
        }
        #endregion // GetPropertyMetaData
    }
}
